#!/usr/bin/env python
#-*- coding:utf-8 -*-
# Copyright (c) 2011-2012 Chanrithy Thim
#
# AUTHOR:
# Chanrithy Thim <12rithy@gmail.com>
#
# This file is part of Appshell
#
# Appshell is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License as published
# by the Free Software Foundation; either version 2 of the License, or (at
# your option) any later version.
#
# Appshell is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with AptUrl; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

import os
import shutil
import statvfs
import subprocess
import sys

from xml.etree import ElementTree as ET

def partition_freespace(directory):
    """Return free space of given directory's partition."""
    st = os.statvfs(directory)
    return st[statvfs.F_BSIZE] * st[statvfs.F_BFREE]

# Process manager
def run_cmd(cmd):
    """Run command and report return value and output."""
    p = subprocess.Popen(cmd, shell=True,
            stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    out, err = p.communicate()
    return (p.returncode, out, err)

def human_readable_size(size = 0):
    symbols, depth = [' B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'], 0

    while size > 1000 and depth < 8:
        size = float(size / 1024)
        depth += 1

    return size, symbols[depth]

def prefix(a, b):
    """Check if sequence a is a prefix of sequence b."""
    if len(a) > len(b):
        return False
    for i in range(0, len(a)):
        if a[i] != b[i]:
            return False
    return True

def remove_prefix(a, b):
    """Remove prefix a from sequence b."""
    assert prefix(a, b)
    return b[len(a):]
    
# recursively remove empty dirs starting from dirpath
def rmdirs(dirpath):
    if os.path.isdir(dirpath) and not os.listdir(dirpath):
        print _("Removing empty dir: %s") % dirpath
        os.rmdir(dirpath)
        rmdirs(os.path.dirname(dirpath))

def remove_with_path(fpath):
    if os.path.isfile(fpath) or os.path.islink(fpath):
        os.unlink(fpath)
    elif os.path.isdir(fpath) and not os.listdir(fpath):
        os.rmdir(fpath)
    else:
        print "ERROR: Installed file %s does not exist on system [Probably you manually deleted]" % fpath
        return False

    # remove emptied directories
    dpath = os.path.dirname(fpath)
    while dpath != '/' and not os.listdir(dpath):
        os.rmdir(dpath)
        dpath = os.path.dirname(dpath)
    return True

def read_link(link):
    """Return the normalized path which is pointed by the symbolic link."""
    # tarfile module normalizes the paths pointed by symbolic links. This
    # causes problems as the file hashes and sizes are calculated before
    # this normalization.
    return os.path.normpath(os.readlink(link))

def join_path(a, *p):
    """Join two or more pathname components.
    
    Python os.path.join cannot handle '/' at the start of latter components.
    
    """
    path = a
    for b in p:
        b = b.lstrip('/')
        if path == '' or path.endswith('/'):
            path +=  b
        else:
            path += '/' + b
    return path

def dir_size(dir):
    """Calculate the size of files under a directory."""
    # It's really hard to give an approximate value for package's
    # installed size. Gettin a sum of all files' sizes if far from
    # being true. Using 'du' command (like Debian does) can be a
    # better solution :(.
    # Not really, du calculates size on disk, this is much better -- exa

    if os.path.exists(dir) and (not os.path.isdir(dir) and not os.path.islink(dir)):
        #so, this is not a directory but file..
        return os.path.getsize(dir)

    if os.path.islink(dir):
        return long(len(read_link(dir)))

    def sizes():
        for root, dirs, files in os.walk(dir):
            yield sum([os.path.getsize(join_path(root, name)) for name in files if not os.path.islink(join_path(root, name))])
    return sum(sizes())

